﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Windows.Forms;
using LevelEditor.App;
using LevelEditor.Components;
using LevelEditor.Components.Layers;
using LevelEditor.Objects.Tiles;

namespace LevelEditor.Objects
{
    public class Library : FlowLayoutPanel
    {
        public enum Session
        {
            Tiles, Chars, Items, Doors, 
        }

        private LibraryItem selectedItem;
        public LibraryItem CurrentSelectedItem
        {
            get { return selectedItem; }
        }

        private int distanceForDrag;
        private Point mouseDownPosition;
        private bool doDragging;

        private Dictionary<Tile.TileType, int> sessionsIndexes;

        private LevelEditor editor;

        public Library()
        {
            this.ControlAdded += Library_ControlAdded;
            distanceForDrag = 2;
            this.AutoScroll = true;
            sessionsIndexes = new Dictionary<Tile.TileType, int>();
        }

        public void SetForm(LevelEditor editor)
        {
            this.editor = editor;
        }

        void Library_ControlAdded(object sender, ControlEventArgs e)
        {
            if (e.Control.GetType() != typeof(LibraryItem)) return;
            
            LibraryItem item = ((LibraryItem)e.Control);
            this.Controls.Add(item);
            switch (item.Tile.myType)
            {
                case Tile.TileType.Character:
                    Controls.SetChildIndex(item, sessionsIndexes[Tile.TileType.Character] + 1);
                    break;
                case Tile.TileType.CommonTile:
                    Controls.SetChildIndex(item, sessionsIndexes[Tile.TileType.CommonTile] + 1);
                    break;
                case Tile.TileType.Door:
                    Controls.SetChildIndex(item, sessionsIndexes[Tile.TileType.Door] + 1);
                    break;
                case Tile.TileType.Item:
                    Controls.SetChildIndex(item, sessionsIndexes[Tile.TileType.Item] + 1);
                    break;
            }

            e.Control.MouseDown += (s , ev) => Control_MouseDown(e.Control, this.Controls.GetChildIndex(e.Control));
            e.Control.MouseMove += Control_MouseMove;
            e.Control.MouseUp += Control_MouseUp;

            this.ScrollControlIntoView(e.Control);

            this.UpdateSessionsIds();
        }

        void Control_MouseUp(object sender, MouseEventArgs e)
        {
            doDragging = false;
        }

        void Control_MouseMove(object sender, MouseEventArgs e)
        {
            if (!doDragging) return;

            if (Util.Util.Distance(mouseDownPosition, Cursor.Position) > distanceForDrag)
            {
                doDragging = false;
                ((LibraryItem)sender).DoDragDrop(((LibraryItem)sender).Tile, DragDropEffects.Copy | DragDropEffects.Move);
            }
        }

        void Control_MouseDown(object sender, int itemIndex)
        {
            
            doDragging = true;
            mouseDownPosition = Cursor.Position;

            SelectLibraryItem( (LibraryItem)this.Controls[itemIndex] );
        }

        public void SelectLibraryItem(LibraryItem item)
        {
            if (selectedItem != null)
                selectedItem.Deselect();

            selectedItem = item;

            selectedItem.Select();
        }

        public void CopyItem()
        {
            if (this.Controls.Count <= 0) return;
            if (this.selectedItem == null) return;

            Tile tile = null;

            if (typeof(Character) == this.selectedItem.Tile.GetType())
            {
                tile = ((Character)this.selectedItem.Tile).Clone();
                
            }

            LibraryItem item = new LibraryItem(tile, this.editor);
            tile.Father = item;

            item.TileName.Text = "copy " + this.selectedItem.TileName.Text;

            this.Controls.Add(item);
        }

        public void DeleteItem()
        {
            if (selectedItem == null) return;

            this.selectedItem.Delete();
            this.selectedItem = null;
        }

        public void UpdateSessionsIds()
        {
            sessionsIndexes.Clear();
            Tile.TileType[] sessions = (Tile.TileType[])Enum.GetValues(typeof(Tile.TileType));
            for (int k = 0; k < this.Controls.Count; k++)
            {
                if (this.Controls[k].Tag == null) continue;
                for (int j = 0; j < sessions.Length; j++)
                {
                    if (this.Controls[k].Tag.ToString().Equals(sessions[j].ToString()))
                    {
                        sessionsIndexes.Add(sessions[j], this.Controls.GetChildIndex(this.Controls[k]));
                        break;
                    }
                }
            }
        }

        public bool ExistInLibrary(string tileName, Tile.TileType type)
        {
            for (int k = sessionsIndexes[type]; k < this.Controls.Count; k++)
            {
                LibraryItem item = Controls[k] as LibraryItem;
                if (item == null) continue;

                if (item.Tile.Name == tileName) return true;
            }

            return false;
        }

        public LibraryItem RetriveTile(string tileName, Tile.TileType type)
        {
            if (!ExistInLibrary(tileName, type)) return null;

            for (int k = sessionsIndexes[type]; k < this.Controls.Count; k++)
            {
                LibraryItem item = Controls[k] as LibraryItem;
                if (item == null) continue;

                if (item.Tile.Name == tileName) return item;
            }

            return null;
        }

    }
}
